package com.example.test.mail;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;

public class SMTPDemo {

    String host = "192.168.170.92";
    int port = 25;
    String user = "test";
    String password = "123";


    public static void main(String[] args) throws Exception {

        SMTPDemo demo = new SMTPDemo();

        info("Please choose an action:");
        info("  1. send mail with simple smtp (no auth)");
        info("  2. send mail with smtp auth");
        info("  3. connect smtp server with SSL");
        info("Input your choice: ");

        java.io.BufferedReader r = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
        String line = r.readLine();
        if (line.equals("1")) {
            demo.host = prompt("Host", r, demo.host);
            demo.port = prompt("Port", r, demo.port);
            MimeMessage message = assembleMail();
            demo.sendWithSimpleSMTP(message);

        } else if (line.equals("2")) {
            demo.host = prompt("Host", r, demo.host);
            demo.port = prompt("Port", r, demo.port);
            demo.user = prompt("User", r, demo.user);
            demo.password = prompt("Password", r, demo.password);
            MimeMessage message = assembleMail();
            demo.sendWithSMTPAuth(message);

        } else if (line.equals("3")) {
            demo.port = 994;
            demo.host = prompt("Host", r, demo.host);
            demo.port = prompt("Port", r, demo.port);
            demo.user = prompt("User", r, demo.user);
            demo.password = prompt("Password", r, demo.password);

            demo.testSMTPAuthWithSSL();

        } else {
            info("Nothing to do!");
        }
    }


    private static String prompt(String label, java.io.BufferedReader r, String defaultValue) throws java.io.IOException {
        info(label + (defaultValue != null ? (" (" + defaultValue + ')') : "") + ": ");
        String line = r.readLine();
        if (line != null) {
            line = line.trim();
        }
        return (line != null) && (line.length() > 0) ? line : defaultValue;
    }


    private static int prompt(String message, java.io.BufferedReader r, int defaultValue) throws java.io.IOException {
        String value = prompt(message, r, String.valueOf(defaultValue));
        try {
            return Integer.parseInt(value);
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }


    private static MimeMessage assembleMail() throws MessagingException {
        MimeMessage message = new MimeMessage((Session) null);

        // 设置邮件的标题和内容
        message.setSubject("test subject");
        message.setText("test content");

        // 设置邮件的发送方 (注意, 当使用smtp auth时, 大部分smtp服务器要求from和auth帐号相同)
        //message.setFrom(new InternetAddress("user1@test.com"));
        message.setFrom(new InternetAddress("17702198591@163.com"));

        // 添加两个收件人
        message.addRecipient(Message.RecipientType.TO, new InternetAddress("to1@test.com"));
        message.addRecipient(Message.RecipientType.TO, new InternetAddress("to2@test.com"));

        // 添加一个抄送方
        message.addRecipient(Message.RecipientType.CC, new InternetAddress("cc1@test.com"));

        // 保存变更
        message.saveChanges();

        return message;
    }


    public void sendWithSimpleSMTP(MimeMessage message) throws MessagingException {

        Properties properties = new Properties(System.getProperties());

        // 打开调试开关
        properties.put("mail.debug", "true");

        // 设置 SMTP 服务器及端口, 如果使用使用标准端口 25, 也可以不配置端口
        properties.put("mail.smtp.host", host);
        properties.put("mail.smtp.port", String.valueOf(port));

        // 生成 javamail session 和 transport 对象
        Transport transport = Session.getInstance(properties).getTransport("smtp");

        // 连接 SMTP 服务器
        transport.connect();

        try {
            // 发送邮件
            transport.sendMessage(message, message.getAllRecipients());
        } finally {
            // 关闭 SMTP 连接
            transport.close();
        }
    }


    public void sendWithSMTPAuth(MimeMessage message) throws MessagingException {

        Properties properties = new Properties(System.getProperties());

        // 打开调试开关
        properties.put("mail.debug", "true");

        // 配置使用 SMTP 身份验证
        properties.put("mail.smtp.auth", "true");

        // 生成 javamail session 和 transport 对象
        //Transport transport = Session.getInstance(properties).getTransport("smtp");
        Transport transport = Session.getInstance(properties).getTransport("smtps");

        // 连接并进行 SMTP 身份验证
        transport.connect(host, port, user, password);

        try {
            // 发送邮件
            transport.sendMessage(message, message.getAllRecipients());
        } finally {
            // 关闭 SMTP 连接
            transport.close();
        }
    }


    public void testSMTPAuthWithSSL() throws javax.mail.MessagingException {
        if (!checkJavaSecurityIssues()) {
            return;
        }

        Properties props = new Properties(System.getProperties());

        // 打开调试开关
        props.put("mail.debug", "true");

        // 配置使用 SMTP 身份验证
        props.put("mail.smtp.auth", "true");

        // 忽略所有证书错误
        props.put("mail.smtps.ssl.trust", "*");

        // 生成 javamail session 和 transport 对象
        Transport transport = Session.getInstance(props).getTransport("smtps");

        // 连接并进行 SMTP 身份验证
        transport.connect(host, port, user, password);

        // 关闭 SMTP 连接
        transport.close();
    }


    private static boolean checkJavaSecurityIssues() {
        // 注，此方法要求 javamail 1.4.2+
        try {
            Class.forName("com.sun.mail.util.MailSSLSocketFactory");
        } catch (ClassNotFoundException e) {
            info("javamail 1.4.2+ is required!");
            return false;
        }

        // 如果是 java 1.5 之前的版本，javamail 的实现还存在 bug 不过可以手工修正
        try {
            javax.net.ssl.TrustManagerFactory.getInstance("X509");
            return true;
        } catch (Exception e) {
            java.security.Provider[] providers = java.security.Security.getProviders("TrustManagerFactory.SunX509");
            if ((providers != null) && (providers.length > 0)) {
                info("earlier java version found (etc. 1.4), trying to fix");
                providers[0].setProperty("TrustManagerFactory.X509",
                        providers[0].getProperty("TrustManagerFactory.SunX509"));
                return true;
            }
            info("java is not supporting SSL: "
                    + System.getProperty("java.vendor") + ' ' + System.getProperty("java.version"));
        }
        return false;
    }


    private static void info(String s) {
        // CS:AllowPrintln
        System.out.println(s);
        // CS:RejectPrintln
    }
}

